/*
 * ADS7843.c
 *
 * Created: 2012-06-02 14:37:42
 *  Author: Sebastian_2
 */ 

#include "../conf.h"
#include "../misc.h"
#include "XMEGA.h"
#include "ADS7843.h"

void ADS7843_Init() {
	#ifndef ATMEGA
	USART_SPI_Init(&ADS7843_USART, ADS7843_BAUD);
	
	ADS7843_PORT.DIRSET = ADS7843_CS_bm;
	ADS7843_PORT.OUTSET = ADS7843_CS_bm;
	
	ADS7843_PORT.DIRCLR = ADS7843_INT_bm;
	ADS7843_PORT.PIN3CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_FALLING_gc | PORT_INT0LVL_MED_gc;
	ADS7843_PORT.INT0MASK = ADS7843_INT_bm;
	
	PMIC.CTRL |= PMIC_MEDLVLEN_bm;
	
	#else
	
	setup_spi(SPI_MODE_0, SPI_MSB, SPI_NO_INTERRUPT, SPI_MSTR_CLK64);
	#ifdef ATMEGA
	SPCR |= (1 << SPR1) | (1 << SPR0);
	SPSR |= (1 << SPI2X);
	#endif
	ADS7843_BUSY_DDR &= ~(1 << ADS7843_BUSY_BIT);
	ADS7843_CS_DDR |= (1 << ADS7843_CS_BIT);
	ADS7843_CS_PORT |= (1 << ADS7843_CS_BIT);
	ADS7843_INT_DDR &= ~(1 << ADS7843_INT_BIT);
	ADS7843_INT_PORT &= ~(1 << ADS7843_INT_BIT);

	EIMSK |= (1 << 1);
	EICRA |= (1 << 3);
	
	#endif
}

point ADS7843_GetXY() {
	point p;
	uint16_t tmp;

	#ifdef ATMEGA
	SPCR |= (1 << SPR1) | (1 << SPR0); 
	#endif

	// X
#ifndef ATMEGA
	USART_SPI_Write(&ADS7843_USART ,0x90);
	tmp = USART_SPI_Read(&ADS7843_USART);
#else
	send_spi(0x90);
	tmp = send_spi(0x00);
#endif
	
	tmp <<= 5;
#ifndef ATMEGA
	tmp |= (USART_SPI_Read(&ADS7843_USART) >> 3);
#else
	tmp |= (send_spi(0x00) >> 3);
#endif
	p.x = tmp;

	// Y
#ifndef ATMEGA
	USART_SPI_Write(&ADS7843_USART ,0xD0);
	tmp = USART_SPI_Read(&ADS7843_USART);
#else
	send_spi(0xD0);
	tmp = send_spi(0x00);
#endif
	
	tmp <<= 5;
#ifndef ATMEGA
	tmp |= (USART_SPI_Read(&ADS7843_USART) >> 3);
#else
	tmp |= (send_spi(0x00) >> 3);
#endif
	p.y = tmp;
	
	#ifdef ATMEGA
	SPCR = 0x50;
	#endif

	return p;
}

point ADS7843_GetSamples() {
	uint16_t resultX, resultY;
	uint16_t X[ADS7843_SAMPLES], Y[ADS7843_SAMPLES];
	point screen;
	
#ifndef ATMEGA
	ADS7843_CS_CLR();
#else
	ADS7843_CS_PORT &= ~(1 << ADS7843_CS_BIT);
#endif

	// gather values from ADC	
	for(uint8_t i = 0; i < ADS7843_SAMPLES; i++) {
		point p = ADS7843_GetXY();
		X[i] = p.x;
		Y[i] = p.y;
	}

#ifndef ATMEGA
	ADS7843_CS_SET();
#else
	ADS7843_CS_PORT |= (1 << ADS7843_CS_BIT);
#endif

	bubbleSort(&X[0], ADS7843_SAMPLES);
	bubbleSort(&Y[0], ADS7843_SAMPLES);

	resultX = 0;
	resultY = 0;

	for(uint8_t i = 0; i < ADS7843_SAMPLES; ++i) {
		resultX += X[i];
		resultY += Y[i];
	}

	screen.x = resultX/ADS7843_SAMPLES;
	screen.x /= 13;
	screen.y = resultY/ADS7843_SAMPLES;
	screen.y /= 17;
	
	return screen;
}

void ADS7843_DetectGesture(uint8_t count, point screen[]) {
	uint8_t left, right, up, down;
	left = 0; right = 0; up = 0; down = 0;
	for(uint8_t i = 0; i < count-1; i++) {
		if(isInRange(screen[i].x - screen[i+1].x, 15, 50))
			left++;
		else if(isInRange(screen[i+1].x - screen[i].x, 15, 50))
			right++;
		else if(isInRange(screen[i].y - screen[i+1].y, 15, 70))
			up++;
		else if(isInRange(screen[i+1].y - screen[i].y, 15, 70)) 
			down++;
	}
	gGesture = 0;
	if(right == 0 && left == 0 && up == 0 && down == 0) {
		gGesture = GESTURE_POINT;
		return;
	}	
	
	if(right - left >= 3) 
		gGesture |= GESTURE_RIGHT;
	else if(left - right >= 3)
		gGesture |= GESTURE_LEFT;
	else if(up - down >= 3)
		gGesture |= GESTURE_UP;
	else if(down - up >= 3)
		gGesture |= GESTURE_DOWN;
}

void bubbleSort(uint16_t* array, uint8_t size) {
    int swapped;
    uint8_t i;
    for (i = 1; i < size; i++)
    {
        swapped = 0;    //this flag is to check if the array is already sorted
        uint8_t j;
        for(j = 0; j < size - i; j++)
        {
            if(array[j] > array[j+1])
            {
                int temp = array[j];
                array[j] = array[j+1];
                array[j+1] = temp;
                swapped = 1;
            }
        }
        if(!swapped){
            break; //if it is sorted then stop
        }
    }
 }